package com.wei.czz.framework.common.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.wei.czz.common.dto.common.NameValue;
import com.wei.czz.common.dto.common.sms.SendSmsDto;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.common.sms.SmsChannelEnum;
import com.wei.czz.common.enums.common.sms.SmsTypeEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.property.SmsProperty;
import com.wei.czz.framework.common.entity.SmsTemplateEntity;
import com.wei.czz.framework.common.helper.SmsSendHelper;
import com.wei.czz.framework.common.service.SmsService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-06-14 15:52:38
 * className: AliSmsServiceImpl
 * version: 1.0
 * description:
 */
@Service("aliSmsService")
@AllArgsConstructor
public class AliSmsServiceImpl implements SmsService {

    private static final Logger log = LoggerFactory.getLogger(AliSmsServiceImpl.class);

    /**
     * 签名
     */
    private static final String SIGH_NAME = "signName";

    /**
     * 模板ID
     */
    private static final String TEMPLATE = "template";

    private final SmsProperty smsProperty;

    @PostConstruct
    public void init() {
        SmsSendHelper.register(SmsChannelEnum.ALI.getValue(), this);
    }

    @Override
    public SendSmsDto sendSms(String mobile, SmsTemplateEntity smsTemplate, Map<String, String> paramMap) {
        log.info("开始阿里云短信发送操作。mobile={} type={} code={} paramMap={}", mobile,
                SmsTypeEnum.getName(smsTemplate.getType()), smsTemplate.getCode(), paramMap);
        if (Boolean.FALSE.equals(smsProperty.getOpen())) {
            log.warn("未开启短信发送，请确认");
            SendSmsDto sendSmsDto = new SendSmsDto();
            sendSmsDto.setStatus(CommonEnum.ZERO.getValue());
            return sendSmsDto;
        }

        /*
            获取渠道参数映射
         */
        Map<String, NameValue<String>> channelParamMap = this.getChannelParam(smsTemplate.getChannelParam());
        NameValue<String> signName = channelParamMap.get(SIGH_NAME);
        NameValue<String> template = channelParamMap.get(TEMPLATE);
        if (Objects.isNull(signName) || StringUtils.isBlank(signName.getValue())) {
            log.info("阿里云短信签名参数不存在");
            throw new CzzException("阿里云短信模板配置有误，发送失败");
        }
        if (Objects.isNull(template) || StringUtils.isBlank(template.getValue())) {
            log.info("阿里云短信模板ID参数不存在");
            throw new CzzException("阿里云短信模板配置有误，发送失败");
        }

        SmsProperty.AliSmsProperty aliSmsProperty = smsProperty.getAli();

        DefaultProfile profile = DefaultProfile.getProfile(aliSmsProperty.getRegionId(),
                aliSmsProperty.getAccessKeyId(), aliSmsProperty.getAccessKeySecret());
        // 构造阿里云请求客户端对象
        IAcsClient client = new DefaultAcsClient(profile);

        SendSmsRequest smsRequest = new SendSmsRequest();
        // 设置接收短信的手机号
        smsRequest.setPhoneNumbers(mobile);
        // 设置阿里云短信服务签名
        smsRequest.setSignName(signName.getValue());
        // 设置短信模板的名称
        smsRequest.setTemplateCode(template.getValue());
        // 设置短信参数
        smsRequest.setTemplateParam(JSON.toJSONString(paramMap));

        SendSmsDto sendSmsDto = new SendSmsDto();
        sendSmsDto.setStatus(CommonEnum.ZERO.getValue());
        try {
            // 向阿里云短信服务发送消息
            SendSmsResponse smsResponse = client.getAcsResponse(smsRequest);
            log.info("阿里云短信服务发送返回结果：{}", JSON.toJSONString(smsResponse));
            if (!"OK".equals(smsResponse.getCode())) {
                log.error("短信发送失败，请务必及时处理");
                sendSmsDto.setStatus(CommonEnum.ONE.getValue())
                        .setMsg(smsResponse.getMessage());
            }
            Map<String, String> resultMap = new HashMap<>();
            resultMap.put("requestId", smsResponse.getRequestId());
            resultMap.put("bizId", smsResponse.getBizId());
            sendSmsDto.setResultMap(resultMap);
        } catch (ClientException e) {
            log.error("阿里云短信服务api调用异常。message={}", e.getMessage(), e);
            sendSmsDto.setStatus(CommonEnum.ONE.getValue())
                    .setMsg("阿里云短信发送异常");
        } catch (Exception e) {
            log.error("阿里云短信发送异常。message={}", e.getMessage(), e);
            sendSmsDto.setStatus(CommonEnum.ONE.getValue())
                    .setMsg("阿里云短信发送异常");
        }
        log.info("阿里云短信发送操作结束");
        return sendSmsDto;
    }

    @Override
    public SendSmsDto batchSendSms(List<String> mobileList, SmsTemplateEntity smsTemplate, Map<String, String> paramMap) {
        log.error("未实现阿里云批量发送短信");
        throw new CzzException("阿里云短信发送异常");
    }

    @Override
    public Map<String, NameValue<String>> getChannelParam(String channelParam) {
        Map<String, NameValue<String>> paramMap = Optional.ofNullable(channelParam)
                .filter(StringUtils::isNotBlank)
                .map(param -> JSON.parseObject(param, new TypeReference<Map<String, NameValue<String>>>() {}))
                .orElse(Collections.emptyMap());

        Map<String, NameValue<String>> channelParamMap = new LinkedHashMap<>();
        channelParamMap.put(SIGH_NAME, paramMap.getOrDefault(SIGH_NAME, new NameValue<>("签名", StringUtils.EMPTY)));
        channelParamMap.put(TEMPLATE, paramMap.getOrDefault(TEMPLATE, new NameValue<>("模板CODE", StringUtils.EMPTY)));
        return channelParamMap;
    }

}
